﻿using System;
using System.Collections.Generic;

using OOExp = Kernel.OpenOrganizerException;
using OOECode = Kernel.OpenOrganizerException.ErrorCode;

namespace Kernel
{
    public class DataBaseService
    {
        public void PerfomeEventService(IDBService service)
        {
            try
            {
                var events = service.GetPastEvents();

                foreach (var it in events)
                    if (it.Periodicity != Event.EventPeriodicity.None)
                    {
                        TimeSpan shift_time = ExtendTime(it.Date,
                                                       it.Periodicity);

                        service.ExtendEvent(it.ID,
                                            it.Date + shift_time,
                                            it.NotificationStart + shift_time,
                                            it.NotificationEnd + shift_time);
                    }
            }
            catch (Exception exp)
            { throw new OOExp(OOECode.FailDataBaseOperation, exp); }
        }

        private TimeSpan ExtendTime(DateTime current,
                                    Event.EventPeriodicity periodicity)
        {
            const int day_per_week = 7;

            TimeSpan result = TimeSpan.FromTicks(0);
            TimeSpan shift_time;

            switch (periodicity)
            {
                case Event.EventPeriodicity.EveryDay:
                    {
                        shift_time = TimeSpan.FromTicks(TimeSpan.TicksPerDay);
                        break;
                    }
                case Event.EventPeriodicity.EveryWeek:
                    {
                        shift_time = TimeSpan.FromTicks(TimeSpan.TicksPerDay *
                                                            day_per_week);
                        break;
                    }
                case Event.EventPeriodicity.EveryMonth:
                    {
                        DateTime dt = new DateTime(0, 1, 0);
                        shift_time = TimeSpan.FromTicks(dt.Ticks);
                        break;
                    }
                case Event.EventPeriodicity.EveryYear:
                    {
                        DateTime dt = new DateTime(1, 0, 0);
                        shift_time = TimeSpan.FromTicks(dt.Ticks);
                        break;
                    }
                case Event.EventPeriodicity.EveryDayWithOutWeekends:
                    {
                        shift_time = TimeSpan.FromTicks(TimeSpan.TicksPerDay);
                        break;
                    }
                default:
                    throw new OOExp(OOECode.UndefinedError);
            }

            Func<DateTime, bool> condition = null;
            if (periodicity == Event.EventPeriodicity.EveryDayWithOutWeekends)
                condition = new Func<DateTime, bool>((DateTime dt) =>
                    {
                        return dt < DateTime.Now ||
                               dt.DayOfWeek == DayOfWeek.Sunday ||
                               dt.DayOfWeek == DayOfWeek.Saturday;
                    });
            else
                condition = new Func<DateTime, bool>((DateTime dt) =>
                    {
                        return dt < DateTime.Now;
                    });

            do
            {
                result += shift_time;
                current += shift_time;
            }while(condition(current));

            return result;
        }
    }
}
